﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.WebUtilities;
using Nuanyang.Asp.Net.Core.Extension.Utils;
using Serilog;
using Serilog.Core;


namespace Nuanyang.Asp.Net.Core.Extension.Middleware
{
    public class RequestLogMiddleware
    {
        private RequestDelegate _next;
        private ILogger _log;

        /// <summary>
        /// 应用程序访问日志收集
        /// </summary>
        /// <param name="next">管道下一个中间件</param>
        /// <param name="printInConsole">是否在控制台打印</param>
        /// <param name="logfileName">日志文件名</param>
        public RequestLogMiddleware(RequestDelegate next, ILogger logger)
        {
            _next = next;
            _log = logger.ForContext(typeof(RequestLogMiddleware));
        }

        /// <summary>
        /// 异常收集及异常处理
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext context)
        {
            await HandleRequestnAsync(context);
            await _next(context);

        }

        /// <summary>
        /// 记录请求信息
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private async Task HandleRequestnAsync(HttpContext context)
        {

            _log.Information("请求来源:{0}", context.Connection.RemoteIpAddress.ToString());
            _log.Information("请求路径:{0},请求类型:{1},请求QueryString:{2}", context.Request.Path, context.Request.Method, context.Request.QueryString.ToUriComponent());
            _log.Information("请求类型:{0}}", context.Request.Method);
            _log.Information("请求QueryString:{0}", context.Request.QueryString.ToUriComponent());
            if (context.Request.HasFormContentType)
            {
                string list = string.Empty;
                foreach (var item in context.Request.Form)
                {
                    list += string.Format("{0}={1} ", item.Key, item.Value);
                }
                _log.Information("参数类型:FormContent:{0}", list);
            }
            if (context.Request.Body.CanRead && !context.Request.Body.CanSeek)
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    //改写request body 可多次读取
                    context.Request.Body.CopyToAsync(memoryStream).GetAwaiter().GetResult();
                    context.Request.Body = new MemoryStream();
                    context.Response.RegisterForDispose(context.Request.Body);
                    memoryStream.Reset();
                    memoryStream.CopyToAsync(context.Request.Body).GetAwaiter().GetResult();
                    context.Request.Body.Reset();
                    memoryStream.Reset();
                    _log.Information("参数类型:Body");
                    using (StreamReader reader = new StreamReader(memoryStream))
                    {
                        _log.Information(await reader.ReadToEndAsync());
                    }
                }
            }
        }
    }
}
